What is NoSQL injection?
NoSQL injection is a vulnerability that lets a malicious hacker introduce (inject) undesired code into database queries executed by NoSQL databases.
What is NoSQL?
The term NoSQL (non-SQL or not only SQL) is used to describe non-relational databases in general and may refer to many different types of databases and data models, including key-value, key-document, column-family, and graph databases. NoSQL databases have rapidly gained popularity in recent years, with mainstream products such as MongoDB, Apache Cassandra, Apache HBase, Apache CouchDB, Neo4j, RavenDB, Redis, OrientDB, DynamoDB, HyperTable, Google Cloud Datastore, and many more. NoSQL database engines use different data structures than relational databases and while they usually do not support SQL statements or SQL queries, they all provide ways for users to execute queries. Unlike with SQL databases, there is no common query language or syntax, so the query format depends on the specific database product and the implementation details of the web application or API. This means your queries will vary depending not only on the database but also on the programming language (e.g. Python, PHP, Node.js, etc.) and framework (e.g. Spring). Even so, most NoSQL queries are based on JSON, and they will often include user input. This means that – as always with unsanitized user inputs – NoSQL databases can also be vulnerable to injection attacks.
How does NoSQL injection work?
NoSQL injections don’t rely on a common query language, so a given injection vulnerability affects only one specific NoSQL database type. Apart from that, NoSQL injection attacks are similar to traditional SQL injection attacks – the attacker provides a malicious payload in user input, such as forms or HTTP requests, and if that input is delivered to the NoSQL database without sanitization, it may cause the database to execute commands supplied by the attacker.
Examples of NoSQL injection
To understand how a NoSQL query is constructed and where it may be vulnerable to an injection attack, we will focus on MongoDB as the most popular NoSQL database, accessing it using PHP. Here is a simple example that accesses a MongoDB database to perform authentication:
$username = $_POST['username'];
$password = $_POST['password'];
$connection = new MongoDB\Client('mongodb://localhost:27017');
if($connection) {
$db = $connection->test;
$users = $db->users;
$query = array(
"user" => $username,
"password" => $password
);
$req = $users->findOne($query);
}
As you can see, the username and password parameters used for authentication are taken from a POST request and then directly inserted into the query. Similar to other types of injection, this allows a malicious user to enter a NoSQL injection payload that provides unauthenticated access. To perform a successful MongoDB injection, it could be enough to supply the following malicious input data in a POST request:
username[$eq]=admin&password[$ne]=foo
The [$ne] query operator means not equal, so the resulting query will find the first record where the username is admin and the password is not foo. If such code is used for authentication and the admin user exists, the attacker will be logged in as that user. Other MongoDB operators can be abused in a similar fashion, for example, [$lt] and [$gt] as well as [$ regex ] . Using regular expressions in the above scenario, attackers might even be able to enumerate all users by trying various combinations in sequence and evaluating the results.